﻿/*==============================================================================
Copyright (c) 2019 PTC Inc. All Rights Reserved.

Copyright (c) 2010-2014 Qualcomm Connected Experiences, Inc.
All Rights Reserved.
Confidential and Proprietary - Protected under copyright and other laws.
==============================================================================*/

using UnityEngine;
using UnityEngine.Events;
using Vuforia;
using UnityEngine.Video;

/// <summary>
/// A custom handler that implements the ITrackableEventHandler interface.
///
/// Changes made to this file could be overwritten when upgrading the Vuforia version.
/// When implementing custom event handler behavior, consider inheriting from this class instead.
/// </summary>
public class MyDefaultTrackableEventHandler : MonoBehaviour
{
    public enum TrackingStatusFilter
    {
        Tracked,
        Tracked_ExtendedTracked,
        Tracked_ExtendedTracked_Limited
    }

    /// <summary>
    /// A filter that can be set to either:
    /// - Only consider a target if it's in view (TRACKED)
    /// - Also consider the target if's outside of the view, but the environment is tracked (EXTENDED_TRACKED)
    /// - Even consider the target if tracking is in LIMITED mode, e.g. the environment is just 3dof tracked.
    /// </summary>
    ///
    /// TrackingStatusFilter.Tracked , TrackingStatusFilter.Tracked_ExtendedTracked, TrackingStatusFilter.Tracked_ExtendedTracked_Limited
    public TrackingStatusFilter StatusFilter = TrackingStatusFilter.Tracked;

    public UnityEvent OnTargetFound;
    public UnityEvent OnTargetLost;

    protected TrackableBehaviour mTrackableBehaviour;
    protected TrackableBehaviour.Status m_PreviousStatus;
    protected TrackableBehaviour.Status m_NewStatus;
    protected bool m_CallbackReceivedOnce = false;

    //不同的 ImageTarget 修改不同的添加类型(0:图片, 1:视频, 2:模型)，使用 ResourceAddType 判断
    public int mAddType = (int)ResourceAddType.MODEL;

    private VideoController mChildVideoController;
    private ImageController mChildImageController;

    protected virtual void Start()
    {
        LogUtils.debug("MyDefaultTrackableEventHandler Start() mAddType = " + mAddType);

        if (mAddType == (int)ResourceAddType.VIDEO)
        {
            mChildVideoController = gameObject.GetComponentInChildren<VideoController>();
            LogUtils.debug("MyDefaultTrackableEventHandler Start() mChildVideoController=" + mChildVideoController);
        }
        else if(mAddType == (int)ResourceAddType.IMG)
        {
            mChildImageController = gameObject.GetComponentInChildren<ImageController>();
            LogUtils.debug("MyDefaultTrackableEventHandler Start() mChildImageController=" + mChildImageController);
        }

        mTrackableBehaviour = GetComponent<TrackableBehaviour>();
        if (mTrackableBehaviour)
        {
            mTrackableBehaviour.RegisterOnTrackableStatusChanged(OnTrackableStatusChanged);
        }
    }

    protected virtual void OnDestroy()
    {
        if (mTrackableBehaviour)
        {
            mTrackableBehaviour.UnregisterOnTrackableStatusChanged(OnTrackableStatusChanged);
        }
    }

    /**
     *  TrackableBehaviour.Status 解析：
     *      NO_POSE : 没有找到图片
     *      EXTENDED_TRACKED : 追踪到了图片但是图片移出了屏幕外
     *      TRACKED : 追踪到了图片并且图片在屏幕内
     */
    void OnTrackableStatusChanged(TrackableBehaviour.StatusChangeResult statusChangeResult)
    {
        m_PreviousStatus = statusChangeResult.PreviousStatus;
        m_NewStatus = statusChangeResult.NewStatus;

        Debug.LogFormat("Trackable {0} {1} -- {2}",
            mTrackableBehaviour.TrackableName,
            mTrackableBehaviour.CurrentStatus,
            mTrackableBehaviour.CurrentStatusInfo);

        HandleTrackableStatusChanged();
    }

    protected virtual void HandleTrackableStatusChanged()
    {
        LogUtils.debug("MyDefaultTrackableEventHandler HandleTrackableStatusChanged()  m_PreviousStatus= " + m_PreviousStatus + " m_NewStatus=" + m_NewStatus);

        if (!ShouldBeRendered(m_PreviousStatus) &&
            ShouldBeRendered(m_NewStatus))
        {
            OnTrackingFound();
        }
        else if (ShouldBeRendered(m_PreviousStatus) &&
                 !ShouldBeRendered(m_NewStatus))
        {
            OnTrackingLost();
        }
        else
        {
            if (!m_CallbackReceivedOnce && !ShouldBeRendered(m_NewStatus))
            {
                // This is the first time we are receiving this callback, and the target is not visible yet.
                // --> Hide the augmentation.
                OnTrackingLost();
            }
        }

        m_CallbackReceivedOnce = true;
    }

    protected bool ShouldBeRendered(TrackableBehaviour.Status status)
    {
        if (status == TrackableBehaviour.Status.DETECTED ||
            status == TrackableBehaviour.Status.TRACKED)
        {
            // always render the augmentation when status is DETECTED or TRACKED, regardless of filter
            return true;
        }

        if (StatusFilter == TrackingStatusFilter.Tracked_ExtendedTracked)
        {
            if (status == TrackableBehaviour.Status.EXTENDED_TRACKED)
            {
                // also return true if the target is extended tracked
                return true;
            }
        }

        if (StatusFilter == TrackingStatusFilter.Tracked_ExtendedTracked_Limited)
        {
            if (status == TrackableBehaviour.Status.EXTENDED_TRACKED ||
                status == TrackableBehaviour.Status.LIMITED)
            {
                // in this mode, render the augmentation even if the target's tracking status is LIMITED.
                // this is mainly recommended for Anchors.
                return true;
            }
        }

        return false;
    }

    protected virtual void OnTrackingFound()
    {
        LogUtils.debug("--- OnTrackingFound() mAddType=" + mAddType);
        ToastUtil.showToast("识别到了图片");

        if (OnTargetFound != null)
            OnTargetFound.Invoke();

        switch (mAddType)
        {
            case (int)ResourceAddType.IMG:
                LogUtils.debug("--- OnTrackingFound ResourceAddType.IMG mChildImageController = " + mChildImageController);
                if (mChildImageController != null)
                {
                    //mChildImageController.SendMessage("OnTrackingFoundInIC");
                    BroadcastMessage("OnTrackingFoundInIC");
                }
                break;
            case (int)ResourceAddType.VIDEO:
                LogUtils.debug("--- OnTrackingFound ResourceAddType.VIDEO");
                //enableComponents();
                mChildVideoController.SendMessage("OnTrackingFoundInVC");
                break;
            case (int)ResourceAddType.MODEL:
                LogUtils.debug("--- OnTrackingFound ResourceAddType.MODEL");
                SendMessage("OnTrackingFoundInMC"); //向 ModelController 发送消息
                break;
        }
    }

    protected virtual void OnTrackingLost()
    {

        if (OnTargetLost != null)
            OnTargetLost.Invoke();

        LogUtils.debug("--- MyDefaultTrackableEventHandler OnTrackingLost() mAddType=" + mAddType);
        // ToastUtil.showToast("没有识别到图片");

        switch (mAddType)
        {
            case (int)ResourceAddType.IMG:
                LogUtils.debug("--- MyDefaultTrackableEventHandler OnTrackingLost case ResourceAddType.IMG");
                if(mChildImageController != null)
                {
                    mChildImageController.SendMessage("OnTrackingLostInIC", SendMessageOptions.DontRequireReceiver);
                }
                break;
            case (int)ResourceAddType.VIDEO:
                LogUtils.debug("--- MyDefaultTrackableEventHandler OnTrackingLost case ResourceAddType.VIDEO mChildVideoController=" + mChildVideoController);
                if(mChildVideoController != null)
                {
                    LogUtils.debug("MyDefaultTrackableEventHandler 向 mChildVideoController 发送了消息 OnTrackingLostInVC");
                    mChildVideoController.SendMessage("OnTrackingLostInVC", SendMessageOptions.DontRequireReceiver);
                }
                //disableComponentes();
                break;
            case (int)ResourceAddType.MODEL:
                LogUtils.debug("--- MyDefaultTrackableEventHandler OnTrackingLost case ResourceAddType.MODEL");
                //GetComponent("ModelController").SendMessage("OnTrackingLost");   //这个方法会导致 Unity 运行时崩溃或者死机
                this.gameObject.SendMessage("OnTrackingLostInMC", SendMessageOptions.DontRequireReceiver);  //向 ModelController 发送消息
                break;
        }
    }

    //private void enableComponents()
    //{
    //    if (mTrackableBehaviour)
    //    {
    //        var rendererComponents = mTrackableBehaviour.GetComponentsInChildren<Renderer>(true);
    //        var colliderComponents = mTrackableBehaviour.GetComponentsInChildren<Collider>(true);
    //        var canvasComponents = mTrackableBehaviour.GetComponentsInChildren<Canvas>(true);     //Canvas 下包含 VideoPlayer，需要现在 inspector 界面设置其不是禁用状态

    //        // Enable rendering:
    //        foreach (var component in rendererComponents)
    //            component.enabled = true;

    //        // Enable colliders:
    //        foreach (var component in colliderComponents)
    //            component.enabled = true;

    //        // Enable canvas':
    //        foreach (var component in canvasComponents)
    //            component.enabled = true;
    //    }

    //    ToastUtil.showToast("enableComponents");
    //}

    //private void disableComponentes()
    //{
    //    if (mTrackableBehaviour)
    //    {
    //        var rendererComponents = mTrackableBehaviour.GetComponentsInChildren<Renderer>(true);
    //        var colliderComponents = mTrackableBehaviour.GetComponentsInChildren<Collider>(true);
    //        var canvasComponents = mTrackableBehaviour.GetComponentsInChildren<Canvas>(true);

    //        // Disable rendering:
    //        foreach (var component in rendererComponents)
    //            component.enabled = false;

    //        // Disable colliders:
    //        foreach (var component in colliderComponents)
    //            component.enabled = false;

    //        // Disable canvas':
    //        foreach (var component in canvasComponents)
    //            component.enabled = false;
    //    }
    //    LogUtils.debug("disableComponentes");
    //}

}
